#pragma once 

#include "FourthEngineMath.h"
#include "Dynamic_Array.h"

using namespace FourthEngineMath;

struct Physic_Object_Frame;
class Physic_Physic;
class Physic_Contact;
class Physic_Object;
class Physic_World;

// struct used to create Physic Objects
struct Physic_Object_Frame{
	Vector3 m_position;
	Vector3 m_velocity;
	float m_radius;
	float m_angle;
	float m_maxSpeed;
	float m_drag;
	Physic_Object_Frame(){
		m_position = Vector3(0.0f, 0.0f, 0.0f);
		m_velocity = Vector3(0.0f, 0.0f, 0.0f);
		m_radius = 0.0f;
		m_angle = 0.0f;
		m_maxSpeed = 0.0f;
		m_drag = 0.0f;
	};
};

// Physic system that updates position
class Physic_Physic{
private:
	Vector3 m_velocity;

public:
	Physic_Physic();
	~Physic_Physic();

	void Update(Physic_Object *a_Physic_Object, const float a_time);

};

// Contact class that handles contact
class Physic_Contact{
private:

public:
	Physic_Contact();
	~Physic_Contact();

	void contact(Physic_Object *a_Physic_Object_To_Resolve, Physic_Object *a_Physic_Object_To_Resolve_With);
};

// Physic Object to be created in a Physic World
class Physic_Object{
private:
	Vector3 m_position;
	Vector3 m_velocity;
	float m_radius;
	float m_angle;
	float m_maxSpeed;
	float m_drag;

public:
	Physic_Object **m_contact;

	Physic_Object();
	Physic_Object(const Physic_Object_Frame *a_Physic_World_Object_Frame);
	~Physic_Object();

	bool collide();
	bool collide(Physic_Object *a_Physic_Object);

	void setPosition(float a_x, float a_y, float a_z);
	const Vector3 getPosition();
	void setVelocity(float a_x, float a_y, float a_z);
	const Vector3 getVelocity();
	void addVelocity(float a_x, float a_y, float a_z);
	void setRadius(float a_r);
	const float getRadius();
	void addRadius(float a_r);
	void setAngle(float a_angle);
	void addAngle(float a_angle);
	const float getAngle();
	void setMaxSpeed(float a_maxSpeed);
	const float getMaxSpeed();
	void setDrag(float a_drag);
	const float getDrag();
};

// World to be created to use physic system
class Physic_World{
private:
	friend class Physic_Physic;
	friend class Physic_Contact;
	friend class Physic_Object;

	Physic_Physic m_Physic_Physic;
	Physic_Contact m_Physic_Contact;
	Dynamic_Array<Physic_Object *> m_Physic_Object_List;

public:
	Physic_World();
	~Physic_World();

	// set up the physic properties of the world
	void SetPhysic(const float a_x, const float a_y, const float a_z);

	// create objects in physic world 
	Physic_Object *CreateObject(const Physic_Object_Frame *a_Physic_Object_Frame);

	// destroy objects in physic world
	void DestroyObject(Physic_Object *a_Physic_Object);

	// update loop
	void Update(const float a_time);

	// shutdown
	void Shutdown();
};
